package us.versus.them.hmap;

import flash.display.BitmapData;
import flash.display.DisplayObject; 
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.Graphics;

class HeightMap {
	var width : Int;
	var height : Int;
	var map : Array< Array< Float > >;

	public var tileSize : Int;
	public var depth : Int;

	public var screenWidth : Int;
	public var screenHeight : Int;

	public function new( ?image : DisplayObject ) {
		if ( null != image ) {
			this.load( image );
		}
		this.tileSize = 16;
		this.screenWidth = 400;
		this.screenHeight = 300;
		this.depth = 16;
	}

	public function load( image : DisplayObject ) {
		this.width = Math.floor( image.width );
		this.height = Math.floor( image.height );
		var bitmapData : BitmapData = new BitmapData( this.width, this.height );
        bitmapData.draw( image );
		this.map = new Array< Array< Float > >();
		for ( y in 0 ... this.height ) {
			var scanLine : Array< Float > = new Array< Float >();
			for ( x in 0 ... this.width ) {
				scanLine.push( this.toFloat( bitmapData.getPixel( x, y ) ) );
			}
			this.map.push( scanLine );
		}
	}

	public function at( x : Int, y : Int ) : Float {
		return this.map[ this.wrap( y, this.height ) ][ this.wrap( x, this.width ) ];
	}

	public function wrap( value : Int, max : Int ) : Int {
		return if ( value >=0 && value < max ) {
			return value;
		} else {
			return ( max + value ) % max;
		}
	}

	public function toFloat( rgb : UInt ) {
		return (
				( ( rgb >> 16 ) & 255 )
				+ ( ( rgb >> 8 ) & 255 )
				+ ( ( rgb ) & 255 )
			   ) / 3 / 255;
	}

	public function draw( 
		graphics:Graphics
		, xOffset:Int
		, yOffset:Int
	) {
		var mag : Int = tileSize * this.depth;

		var xTileSize : Int = this.tileSize;
		var yTileSize : Int = Math.floor( tileSize * 2 / 3 );

		var xTileCount : Int = Math.floor ( this.screenWidth / xTileSize ) + 1;
		var yTileCount : Int = Math.floor ( this.screenHeight / yTileSize ) + 1;

		for ( y in 0 ... yTileCount + 2 ) {
			for ( x in -5 ... xTileCount + 3 ) {

				var h0 = this.at( x + xOffset + 0 - y, y + yOffset + 0 );
				var x0 : Float = ( x + 0 ) * xTileSize;
				var y0 : Float = ( y + 0 ) * yTileSize - mag * h0;

				var h1 : Float = this.at( x + xOffset + 1 - y, y + yOffset + 0 );
				var x1 : Float = ( x + 1 ) * xTileSize;
				var y1 : Float = ( y + 0 ) * yTileSize -  mag * h1;

				var h2 : Float = this.at( x + xOffset + 1 - y, y + yOffset + 1 );
				var x2 : Float = ( x + 2 ) * xTileSize;
				var y2 : Float = ( y + 1 ) * yTileSize -  mag * h2;

				var h3 : Float = this.at( x + xOffset + 0 - y, y + yOffset + 1 );
				var x3 : Float = ( x + 1 ) * xTileSize;
				var y3 : Float = ( y + 1 ) * yTileSize -  mag * h3;

				var s = ( 1 + ( h2 - h0 ) ) / 2;
				s *= s;
				var n = Math.floor( s * 255 + 32 );
				if ( n > 255 ) n = 255;
				var g = n * 2 + 8;
				if ( g > 255 ) g = 255;
/*
				var n = 128;
				var g = n;
*/
				graphics.beginFill( n << 16 | g << 8 | n );
				//graphics.beginFill( 0x99FF99 );
					graphics.lineStyle( 0, 0x000020 );
					graphics.moveTo( x0, y0 );
					graphics.lineTo( x1, y1 );
					graphics.lineTo( x2, y2 );
					graphics.lineTo( x3, y3 );
					graphics.lineTo( x0, y0 );
				graphics.endFill();
			}
		}
	}

}
